public class BranchDemo {
    public static boolean isLeapYear(int year) {

        if(0 == year%400) {
            // 能被400整除的年份是闰年
            return true;
        }

        if(0 == year%100) {
            // 不能被400整除 但是能被100整除的年份是 平年
            return false;

        } else if(0 == year%4) {
            // 不能被100整除，但是能被4整除的年份是 润年
            return true;

        } else {

            // 其他的年份是平年
            return false;
        }
    }

    public static int dayNumOfYear(int year, int month) {

        var dayNum = 0;

        switch (month) {
            case 1 : dayNum = 31; break;
            case 3 : dayNum = 31; break;
            case 5 : dayNum = 31; break;
            case 7 : dayNum = 31; break;
            case 8 : dayNum = 31; break;
            case 10: dayNum = 31; break;
            case 12: dayNum = 31; break;
            case 4 : dayNum = 30; break;
            case 6 : dayNum = 30; break;
            case 9 : dayNum = 30; break;
            case 11: dayNum = 30; break;
            case 2 : dayNum = isLeapYear(year) ? 29 : 28; break;
            default: dayNum = 0;
        }

        return dayNum;
    }


    /**
     2019年1月1日 是周二，以此为基准，计算一个日期对应的星期

     @param year 闭区间[-2000, 4000]
     @param month 1base
     @param day 1base
     @return 1base week day, -1 if not a valid day
     */
    public static int computeWeekDayOfYear(int year, int month, int day) {
        //

        //入参校验
        if (!(year >= -2000 && year<=4000)) {
            // 年数字不合法
            return -1;
        }

        int monthDayNum = dayNumOfYear(year, month);
        if (0 == monthDayNum) {
            // 月数字不合法
            return -1;
        }

        if (day < 1 || day > monthDayNum) {
            // 日数字不合法
            return -1;
        }

        // 计算和基准日期的差值, 2019年1月1日 是周二
        final int baseYear = 2019;
        final int  baseMonth = 1;
        final int  baseDay = 1;
        final int  baseWeekDay = 1; // 周二，但是用 0 base, 记为1

        int diffDayNum = 0;

        // 计算累加 年的天数差值
        int tmpY = baseYear;
        while(tmpY > year) {
            // 如果baseyear 比较大，逐年减小之，按平闰年累加 diffDayNum
            tmpY -= 1;
            diffDayNum -= isLeapYear(tmpY) ? 366 : 365;
        }
        while(tmpY < year) {
            // 如果baseyear 比较小，逐年增大之，按平闰年累加 diffDayNum
            diffDayNum += isLeapYear(tmpY) ? 366 : 365;
            tmpY+=1;
        }

        // 计算累加 月的天数差值
        int tmpM = baseMonth;
        while (tmpM < month) {
            // baseMonth 一定不大于 month
            // 逐月增加，累加月份天数到 diffDayNum
            diffDayNum += dayNumOfYear(year, tmpM);
            tmpM+=1;
        }

        // 计算累加 日的天数差值
        diffDayNum += day-baseDay;

        int weekDay = (baseWeekDay + diffDayNum)%7; // 计算 0 base 星期几
        if(weekDay < 0){
            weekDay += 7;
        }

        weekDay += 1; // 换算成 1 base 星期几

        return weekDay;
    }

    protected static void demoLogic() {
        for (int y=1999; y<=2022; ++y) {

            for (int m=2; m<=12; ++m) {

                int days = dayNumOfYear(y, m);
                System.out.println(y+"年"+m+"月 有"+days+"天");

                for (int d=26; d<=31; ++d) {

                    int weekDay = computeWeekDayOfYear(y, m, d);

                    String weekStr = weekDay<0 ? "无效日期" : "星期"+weekDay;
                    System.out.println(y+"年"+m+"月"+d+"日 -> "+weekStr);
                    //break;
                }

                break;
            }
            //break;
        }
    }
}
